package views

import (
	"fmt"
	tea "github.com/charmbracelet/bubbletea"
	"github.com/charmbracelet/lipgloss"
	"github.com/evertras/bubble-table/table"
	"math/rand"
	"strings"
)

const (
	columnKeyID = "id"

	numCols = 100
	numRows = 10
	idWidth = 5

	colWidth = 5
	maxWidth = 160
)

type ScrollModel struct {
	scrollableTable table.Model
	Cols            []table.Column
	Rows            []table.Row
	preview         Preview
}

var (
	styleSubtle = lipgloss.NewStyle().Foreground(lipgloss.Color("#888"))

	styleBase = lipgloss.NewStyle().
			Foreground(lipgloss.Color("#ffffff")).
			BorderForeground(lipgloss.Color("#ffffff")).
			Align(lipgloss.Center)
)

func colKey(colNum int) string {
	return fmt.Sprintf("%d", colNum)
}

func genRow(id int) table.Row {
	data := table.RowData{
		columnKeyID: fmt.Sprintf("ID %d", id),
	}

	for i := 0; i < numCols; i++ {
		data[colKey(i)] = colWidth
	}

	return table.NewRow(data)
}

func GetBOrder() table.Border {
	return table.Border{
		Top:    "─",
		Left:   "│",
		Right:  "│",
		Bottom: "─",

		TopRight:    "┐",
		TopLeft:     "┌",
		BottomRight: "┘",
		BottomLeft:  "└",

		TopJunction:    "┬",
		LeftJunction:   "├",
		RightJunction:  "┤",
		BottomJunction: "┴",
		InnerJunction:  "┼",

		InnerDivider: "│",
	}
}
func NewModel() ScrollModel {
	var rows []table.Row

	for i := 0; i < numRows; i++ {
		row := genRow(i)
		row.Style = lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("231"))
		rows = append(rows, row)
	}

	cols := []table.Column{
		table.NewColumn(columnKeyID, "ID", idWidth),
	}

	for i := 0; i < numCols; i++ {
		cols = append(cols, table.NewColumn(colKey(i), colKey(i+1), rand.Intn(7)+colWidth))
	}
	t := table.New(cols).
		WithRows(rows).
		WithBaseStyle(styleBase).
		WithMaxTotalWidth(maxWidth).
		Focused(true).
		Border(GetBOrder()).
		HighlightStyle(lipgloss.NewStyle().Foreground(lipgloss.Color("229")).
			Background(lipgloss.Color("57")).
			Bold(false))

	return ScrollModel{
		scrollableTable: t,
	}
}

func (m ScrollModel) Init() tea.Cmd {
	return nil
}

func (m ScrollModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
	var (
		cmd  tea.Cmd
		cmds []tea.Cmd
	)

	// 更新数据

	m.scrollableTable, cmd = m.scrollableTable.Update(msg)

	cmds = append(cmds, cmd)

	switch msg := msg.(type) {
	case tea.KeyMsg:
		switch msg.String() {
		case "ctrl+c", "esc", "q":
			cmds = append(cmds, tea.Quit)
		case "r":
			m.scrollableTable = m.scrollableTable.WithColumns(m.Cols).WithRows(m.Rows)
		case "p":
			row := m.scrollableTable.HighlightedRow()
			m.preview = Preview{
				Data:   row.Data,
				Parent: &m,
			}
			return m.preview, nil
		}
	}

	return m, tea.Batch(cmds...)
}

func (m ScrollModel) View() string {
	body := strings.Builder{}

	body.WriteString("A scrollable table\nPress shift+left or shift+right to scroll\nPress q or ctrl+c to quit\n\n")

	body.WriteString(m.scrollableTable.View())

	return body.String()
}
